Salesforce Apex vs Synrc FormalTalk

[Biased] порівняльна характеристика Salesforce Apex та FormalTalk.

Мова для CRM/ERP системи

Якщо класифікувати FormalTalk, як мову згідно номенклатури, яка використовується в моій Енциклопедії Мов Програмування, то FormalTalk займає місце серед когорти мов які використовуються для промислових ERP систем. Візьме до прикладу Salesforce Apex (не путати з Oracle Apex, але якшо взяти і його, то нічого в статті не зміниться) і порівняємо її повністю імперативну мову Apex з вбудованою підмовою даних SOQL (щось подібне до LINQ).

Основне завдання цих недолугих мов, які не є мовами програмування загального призначення полягає в управлінні типовими специфікаціями та логікою складних продуктів з важкими рантаймами, а не для створення продуктів та їх лінковки в більш низькорівневій та загальній манері.

Salesfore Apex разом з вбудованим SOQL

Contact[] cc = [SELECT Id FROM Contact LIMIT 2]; Task[] tt = [SELECT Id FROM Task WHERE WhoId IN :cc]; String[] ss = new String[]{'a', 'b'}; Account[] aa = [SELECT Id FROM Account WHERE AccountNumber IN :ss]; String myString1 = 'aaa', myString2 = 'bbb', myString4 = 'ccc'; Integer myInt3 = 11, myInt5 = 22; // A SOSL query with binds in all possible clauses List> searchList = [FIND :myString1 IN ALL FIELDS RETURNING Account (Id, Name WHERE Name LIKE :myString2 LIMIT :myInt3), Contact, Opportunity, Lead WITH DIVISION =:myString4 LIMIT :myInt5];

При розробці FormalTalk враховувалась 10-річна практика програмування на бібліотеках N2O, яка формалізована у вигляді математичної моделі в System-F та MLTT як специфікація N2O.PRO. Оскільки N2O.PRO покриває модель Закмана, то і мова FormalTalk є своєрідним офіційним скриптом який розповсюджується на усі рівні ISO 42010.

Synrc FormalTalk ISO 42010 BPE

record routeProc begin id = [] : list | operation = [] : [] + atom | feed = [] : [] + binary | type = [] : atom | folder = [] : binary | users = [] : binary + list | folderType = "personal" : binary | callback = [] : [] + function | reject = false : false + boolean | options = [] : [] + list end fun action request to=Archive begin newDoc = proc.docs.hd | newProc = proc | newProc.docs = [newDoc] | unindexUrgent proc newDoc | newState = actionGen req proc newProc | result [ general req newState newDoc | stop ] newState reply proc.executors end route routeTo begin (Cr,R):R,[] | (R,gwND):O,R | (gwND,Det):D,[] | (*,InC):A,To | (gwC,I):A,To,toExecutors | (*,G):G,[];P,M | (*,A):A,[] end

Відмінності між мовами

На відміну від Salesforce Apex, FormalTalk є декларативною мовою, що означає що ви кажете, що ви хочете дістати (навіть якщо це послідовність операцій), а не що робити в якій послідовності. Однак для практики, а саме для перепакування змінних та мінімального набору утилітарних фунцій роботи з записами, списками, словниками, мапами. Мова містить єдиний імперативний оператор присвоювання та обмежені можливості виклику функцій з повним контролем рекурсії.

Мотивація скриптових мов для облікових систем

Головна мотивація, якою користуються компанії при розробці таких мов програмування для масивних ран-таймів — це уніфікація інтерфейсів і повний контроль над усіма перетвореннями, які можуть знадобитися в подальшому (наприклад трансляція в інші мови), а також спосіб перебудовування графічного інтерфейсу та моделі даних системи в реальному часі, що є невід'ємною умовою на тендерах ERP/CRM систем, що було започатковано в таких система як BAAN.

Ці мови є недолугими тому, що вони є в сутності обгортками над реальною системою, і повинні бути зрозумілі операторам, бажано з примітивними синтаксиами. Але LISP та спеціалізовані мови погано продаються, тому будь-яка проста мова для працюючого продукту може виявитися більш ефективною ніж трата часу для пошуку найоптимальнішої мови чи робота у її відсутності.

Контроль над подальшими транформаціями з мови FormalTalk у формальні лямюда мови як System F або фібраційні мови CoC або MLTT, а також обмеження та контроль рекурсії та всіх викливів є такою однією з головних технічних мотивацій, що призведе до драматичного усунення помилок при програмуванні логіки. Перше — транформації — є тим, що відкриває ворота для матаметатичної верифікації декларативної логіки яка записана на мові FormalTalk. Друге — контрольовані виклики та рекурсія — є тим, що дозволяє більш безпосередньо транслювати програми у формальні фібраційні мови.

Мова для веб-фреймворку

Мова FormalTalk може бути одночасно прокласифікована як спеціалізована мова для побудови сайтів, тобто DSL для веб-фреймворка зі своїм лексером та парсером, у цьому сенсі її можна порівняти з UrWeb.

UrWeb

let main () = let fun create r = id <- nextval s; room <- Room.create; dml (INSERT INTO t (Id, Title, Room) VALUES ({[id]}, {[r.Title]}, {[room]})); main () end

У попередній статті ми розказали про BPE, FORM, KVS підмови FormalTalk, а тут покажемо як виглядає класичний приклад N2O.SAMPLE на мові FormalTalk

Synrc FormalTalk ISO 42010 NITRO

module Sample.Index nitro fun room []:list begin ret '/root' end fun room []:binary begin ret '/root' end fun room begin end fun chat message begin nx = n2o:session :room | room = call room nx | user = n2o:user | x = kvs:writer room | y = KVS.writer{args={:msg,kvs:seq,user:var,message:var}} | z = kvs:add y | w = kvs:save z | n2o:send {:topic,room} N2O.client{data={user,message}} end fun display {:msg,_,user:var,message:var} begin nitro:wire NITRO.jq{target=:message,method=[:focus,:select]} | jse = nitro:jse message | nitro:insert_top :history NITRO.message{body=[NITRO.author{body=user:var},jse]} end fun event :logout begin n2o:user [] | nitro:redirect "/app/login.htm" end fun event :chat begin message = nitro:q :message | call chat message end fun event {:client,{user,message}} begin call display {:msg,user,message} end fun event :init begin nx = n2o:session :room | room:var = call room nx | kvs:ensure KVS.writer{id=room} | n2o:subscribe {:topic,room} | n2o:subscribe {n2o.sid} | nitro:update :upload NITRO.upload | nitro:update :heading NITRO.h2{id=:heading,body=room} | nitro:update :logout NITRO.button{id=:logout,body="Logout",postback=:logout} | nitro:update :send NITRO.butto{id=:send,body="Chat",postback=:chat,source=[:message]} | messages = kvs:all room | lists:map messages display end


˙

˙